import sys
import time
import logging
import struct
import threading
from smap.driver import SmapDriver
from smap.loader import SmapLoadError
from smap.util import periodicSequentialCall
import kinterbasdb
import datetime, calendar
from twisted.internet import threads, reactor

class VigilentDriver(SmapDriver):
    def setup(self, opts):
        #create all the data streams (m1c1, m1c2, m2c1, m2c2, etc)
        self.ids = {}
        self.calibrations = {}
        for motename in xrange(1, 56):
            print '/m%i/c1' % motename, opts.get('units_m%ic1' % motename, 'F')
            print '/m%i/c2' % motename, opts.get('units_m%ic2' % motename, 'F')
            t1 = self.add_timeseries('/m%i/c1' % motename, opts.get('units_m%ic1' % motename, 'F'), data_type="double")
            t2 = self.add_timeseries('/m%i/c2' % motename, opts.get('units_m%ic2' % motename, 'F'), data_type="double")
            #print motename
            self.ids[motename] = (t1['uuid'], t2['uuid'])
            calFactor1 = float(opts.get("calFactor_m%ic1" % motename, '1'))
            calConstant1 = float(opts.get("calConstant_m%ic1" % motename, '0'))
            calFactor2 = float(opts.get("calFactor_m%ic2" % motename, '1'))
            calConstant2 = float(opts.get("calConstant_m%ic2" % motename, '0'))
            self.calibrations[motename] = (calFactor1, calConstant1, calFactor2, calConstant2)
        #self.period = opts.get("Period", 5000)
            
    def start(self):
        threads.deferToThread(self.begin_read)

    def begin_read(self):
        """First, open the connection and initiate the query in a thread"""
        #connection to firebird DB
        self.con = kinterbasdb.connect (host = 'localhost', user = 'sysdba', password = 'G3ccFoUw', database = '/home/cbe/fbdata/Brower/FACSDB.FDB')
        self.cursor = self.con.cursor()        
        self.cursor.execute ("SELECT name,A1,A2,datetime_stamp FROM data join motes on data.mac = motes.mac;")
        self.w = 0
        threads.deferToThread(self.read)

    def read(self):    
        """Also in a thread, read 10k records"""
        data = self.cursor.fetchmany(size=10000)
        # pass them back to the reactor thread
        reactor.callFromThread(self.add, data)

    def add(self, data):
        """In the reactor thread, send the data to sMAP"""
        print (len(data)+(self.w*10000)), 'records read'
        self.w += 1
        for row in data:
            motename = int(row[0])
            channel1 = row[1]
            channel2 = row[2]
            motetime = calendar.timegm(row[3].utctimetuple()) + 3600*7 #0 assumes you are in UTC, 7 assumes you are in PST during DST, 8 assumes not during DST
            self._add(self.ids[motename][0], motetime, channel1*self.calibrations[motename][0]+self.calibrations[motename][1])
            self._add(self.ids[motename][1], motetime, channel2*self.calibrations[motename][2]+self.calibrations[motename][3])

        if len(data) < 10000:
            # if we're done, be done
            self.cursor.close()
        else:
            # otherwise, read another chunk
            threads.deferToThread(self.read)
